/**
 * Copyright (c) 2010
 * Bert Young. UESTC. 
 */
 
#ifndef BERT_ENTRYMANAGER_H
#define BERT_ENTRYMANAGER_H

#include <map>
#include "Entry.h"

class EntryManager // : memory pool
{
	/**
	 * Container for manage entries
	 */
	std::map<unsigned int, Entry *> container;

protected:
	/**
	 * Insert entry
	 */
	bool addEntry( Entry * entry)
	{
		return container.insert(std::make_pair(entry->id, entry)).second;
	}
	/**
	 * Remove entry
	 */
	bool removeEntry( Entry * entry)
	{
		return container.erase(entry->id) > 0;
	}
	/**
	 * Remove entry
	 */
	bool removeEntry( unsigned int id)
	{
		return container.erase(id) > 0;
	}
	/**
	 * Get entry
	 */
	Entry * getEntry( unsigned int id )
	{
		std::map<unsigned int, Entry*>::iterator it = container.find(id);
		if ( it != container.end() )
			return it->second;
		else
			return NULL;
	}
	/**
	 * Change the id of an entry
	 */
	bool changeID ( unsigned int oldid, unsigned int newid)
	{
		if ( oldid == newid )
			return true;
		if ( getEntry(newid) != NULL )
			return false;// already exist
		Entry * entry = getEntry(oldid);
		if ( entry == NULL )
			return false;// can not find
		this->removeEntry(entry);
		entry->id = newid;
		if ( addEntry(entry) )
			return true;
		else
		{
			entry->id = oldid;
			this->addEntry(entry);
			return false;
		}
	}
	/**
	 * Size
	 */
	unsigned int size() const
	{
		return container.size();
	}
	/**
	 * Empty?
	 */
	bool empty() const
	{
		return container.empty();
	}
	/**
	 * Clear all entries
	 */
	void clear()
	{
		container.clear();
	}
	/**
	 * Callback on every entry
	 */
	template <typename ENTRY>
	bool execEveryEntry(Callback<ENTRY> & exec)
	{
		std::map<unsigned int,Entry * >::iterator it = container.begin();
		std::map<unsigned int,Entry * >::iterator tmp;
		while ( it != container.end() )
		{
			tmp = it;
			++it;
			if ( !exec.exec((ENTRY *)tmp->second) )
				return false;
		}
		return true;
	}
	/**
	 * Delete all entries
	 */
	void deleteAll()
	{
		std::map<unsigned int, Entry * >::iterator it = container.begin();
		while ( it != container.end() )
		{
			delete it->second;
			++it;
		}
		this->clear();
	}
	
public:
	/**
	 * Destructor
	 */
	virtual ~EntryManager()
	{
		this->deleteAll();
	}
};

#endif
